/**
 * @author sunye
 * 抽象构件接口：定义具体构件类的接口。
 * 具体构件类（被装饰类）：实现抽象构件接口，创建要给被修饰类。
 * 装饰抽象类：实现抽象构件，规定实现类要实现的方法，并组合具体构建类的对象。
 * 具体装饰类：继承装饰抽象类，实现方法。
 *
 * 实际应用:
 *  扩充类功能的一种方式，是继承的替代方案
 *  ---------------------------------------
 *  人话:
 *      A在忙，B去接手A原先的工作
 *      B想修改A的代码但是怕出问题背锅
 *      B使用装饰器模式对A的代码进行装饰，原先逻辑不变制作增加新的方法
 *      不出问题皆大欢喜，出问题只需要确认装饰方法没问题，锅就甩不到B身上
 */

/* 原有的接口，一会要被装饰的构件 */
interface Component {
    void say();

    void eat();
}
/* 原有的实现类，一会要被装饰的构件 */
class ComponentImpl implements  Component{
    @Override
    public void say() {
        System.out.println("hello world");
    }
    @Override
    public void eat() {
        System.out.println("Really delicious");
    }
}
/*抽象的装饰类*/
abstract class  Decorator extends ComponentImpl implements Component {
    Component component;//原有的构件
    //扩充新的方法
    public abstract void WriteCode() ;

    //原有方法保留
    @Override
    public void say() {
        component.say();
    }
    @Override
    public void eat() {
        component.eat();
    }

    public Decorator(Component component) {
        this.component = component;
    }

}
/*装饰类的实现*/
class DecoratorImpl extends Decorator{
    public DecoratorImpl(Component component) {
        super(component);
    }

    @Override
    public void WriteCode() {
            System.out.println("Write Code");
    }
}
public class DecoratorTest {
    public static void main(String[] args) {
        //原先的构件只能say和eat
        Component component = new ComponentImpl();
        component.say();
        component.eat();
        //通过装饰之后能额外增加WriteCode能力了
        System.out.println("----------------------");
        //通过装饰之后能额外增加WriteCode能力了
        DecoratorImpl decoratorCompoent = new DecoratorImpl(component);
        decoratorCompoent.say();
        decoratorCompoent.eat();
        decoratorCompoent.WriteCode();
    }
}
